package org.filecollector.linker;

import lombok.AllArgsConstructor;
import org.filecollector.msgcontroller.MSGController;
import org.filecollector.msgcontroller.answers.AnswerMessage;
import org.filecollector.msgcontroller.answers.SyncAnswerMessage;
import org.filecollector.msgcontroller.requests.RequestMessage;
import org.filecollector.msgcontroller.requests.SyncRequestMessage;

import java.net.URI;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;

@AllArgsConstructor
public class LoopClass extends AbstractLoop {
    MSGController messenger;
    Map<URI, Function<RequestMessage, AnswerMessage>> functions;
    Consumer<String> tracer;
    Consumer<String> informer;
    Runnable loopFunction;

    private void loop() {
        SyncRequestMessage syncMSG = messenger.read();
        Long id = syncMSG.operationID();
        tracer.accept(
                String.format(
                        "Start processing of message id %d",
                        id
                )
        );
        RequestMessage msg = syncMSG.requestMessage();
        var func = functions.get(URI.create(msg.uri()));
        AnswerMessage ret = func.apply(msg);
        messenger.write(new SyncAnswerMessage(id, ret));
        tracer.accept(
                String.format(
                        "Message id %d processed",
                        id
                )
        );
    }

    @Override
    public void run() {
        informer.accept(
                String.format(
                        "Started thread %s", Thread.currentThread().getName()
                )
        );
        while (true) {
            loopFunction.run();
            if (shouldStop()) {
                informer.accept(
                        String.format(
                                "Thread %s terminated", Thread.currentThread().getName()
                        )
                );
                allowContinue();
                break;
            }
        }
        informer.accept(
                String.format(
                        "Thread %s finished", Thread.currentThread().getName()
                )
        );
    }
}
